#include <iostream>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "process.h"
#include <arpa/inet.h>

#if 0
struct sockaddr {
	sa_family_t sa_family;       // 地址族协议, ipv4
	char        sa_data[14];     // 端口(2字节) + IP地址(4字节) + 填充(8字节)
}

struct in_addr
{
    in_addr_t s_addr;
};  

struct sockaddr_in
{
    sa_family_t sin_family;		/* 地址族协议: AF_INET */
    in_port_t sin_port;         /* 端口, 2字节-> 大端  */
    struct in_addr sin_addr;    /* IP地址, 4字节 -> 大端  */
    /* 填充 8字节 */
    unsigned char sin_zero[sizeof (struct sockaddr) - sizeof(sin_family) -
               sizeof (in_port_t) - sizeof (struct in_addr)];
};  
#endif

using namespace std;
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;

/*For socket client*/


/*The function is used for multi-thread test*/

void *client_connect_request(void *arg)
{
    int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd == -1) {
        perror("Fail to init socket");
        return NULL;
    }
    sock_info_t *sock_info = (sock_info_t *)arg;
    struct sockaddr_in client_sockaddr = sock_info->sock_addr;
    int  ret = connect(fd, (sockaddr *)&client_sockaddr, sizeof(sockaddr));
    char ip[32];
    inet_ntop(AF_INET, (const void *)&client_sockaddr.sin_addr.s_addr, ip, sizeof(ip));
    ip[strlen(ip)] = '\0';
    if (ret == -1) {
        perror("Fail to bind socket");
    }

    char data_buf[SOCK_BUFF_LEN];
    int rev_len = 0;
    int number = 0;

    printf("Start client, tid %lu connect server ip %s, port %u\n", pthread_self(),
           ip, ntohs(client_sockaddr.sin_port));
    while (1) {
        bzero(data_buf, sizeof(data_buf));
        snprintf(data_buf, sizeof(data_buf), "Hello server, my number is %d, my tid %lu\n",
                 number, pthread_self());
        send(fd, data_buf, sizeof(data_buf), 0);
        number++;

        bzero(data_buf, sizeof(data_buf));
        rev_len = recv(fd, data_buf, sizeof(data_buf), 0);
        if(rev_len > 0) {
            printf("%s", data_buf);
        } else if (rev_len == 0) {
            printf("server close\n") ;
            break;
        } else {
            perror("Receive error");
            break;
        }
        sleep(1);
        if (number == 15) {
            break;
        }
    }
    free(arg);
    pthread_exit(NULL);
}

#define INTERFACE_NAME "ens33"
#define CLIENT_IP "192.168.107.99"

int main()
{
    sockaddr_in client_sockaddr;
    client_sockaddr.sin_family = AF_INET;
    client_sockaddr.sin_port = htons(9999);
    const char *client_ip = "192.168.107.135";
    inet_pton(AF_INET, client_ip, &client_sockaddr.sin_addr.s_addr);

    sock_info_t *sock_info = NULL;
    pthread_t tid[128];
    int i = 0;
    for(i = 0; i < 128; i++) {
        sock_info = (sock_info_t *)malloc(sizeof(sock_info_t));
        if (sock_info == NULL)  {
            perror("Fail to alloc for sock info");
            continue;
        }
        memcpy(&sock_info->sock_addr, &client_sockaddr, sizeof(sockaddr));
        pthread_create(&tid[i], NULL, client_connect_request, (void *)sock_info);
    }
    printf("Have create %d threads for connect\n", i + 1);

    for(i = 0; i < 128; i++) {
        pthread_join(tid[i], NULL);
    }

    return 0;
}
